package start.aai.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;
import start.aai.common.Ollama.OllamaClient;
import start.aai.entity.DTO.ChatformDTO;
import start.aai.entity.DTO.FileDTO;
import start.aai.entity.DTO.MessageDTO;
import start.aai.entity.Messages;
import start.aai.mapper.MessagesMapper;
import start.aai.service.MessagesService;
import start.aai.utils.FileProcessor;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class MessagesServiceImpl extends ServiceImpl<MessagesMapper, Messages> implements MessagesService {

    @Resource
    private MessagesMapper messagesMapper;

    // 常量定义
    public static final int MAX_FILE_CONTENT_LENGTH = 4000;
    public static final int MAX_FULL_PROMPT_LENGTH = 5000;

    @Transactional
    public Flux<String> chatStream(String text, MultipartFile file,Integer userId) {
        log.info("===== 进入chatStream方法，处理用户请求 =====");
        log.info("当前对话id: {}", MessageDTO.conversationid);
        try {
            // 1. 封装用户输入
            MultipartFile[] files = file != null ? new MultipartFile[]{file} : null;
            ChatformDTO chatform = new ChatformDTO(text, files);
            log.debug("用户输入文本: {}", text);
            log.debug("上传文件: {}", file != null ? file.getOriginalFilename() : "无");

            // 2. 处理文件内容
            String userInput = chatform.getText() != null ? chatform.getText().trim() : "";
            List<String> imageBase64List = new ArrayList<>();
            StringBuilder fileTextBuilder = new StringBuilder();

            if (files != null) {
                for (MultipartFile uploadedFile : files) {
                    if (uploadedFile == null || uploadedFile.isEmpty()) {
                        log.warn("跳过空文件");
                        continue;
                    }
                    String fileName = uploadedFile.getOriginalFilename();
                    log.info("处理文件: {}", fileName);

                    if (FileProcessor.isImageFile(fileName)) {
                        String base64 = FileProcessor.imageToBase64(uploadedFile);
                        imageBase64List.add(base64);
                        log.debug("图片转Base64成功，长度: {}", base64.length());
                    } else {
                        String content = null;
                        if (fileName != null) {
                            content = FileProcessor.processFile(uploadedFile, fileName);
                        }
                        if (content != null) {
                            content = FileProcessor.limitContentLength(content, MAX_FILE_CONTENT_LENGTH);
                            fileTextBuilder.append("文件名称：").append(fileName).append("\n")
                                    .append("文件内容：").append(content).append("\n\n");
                            log.debug("文件内容处理完成，长度: {}", content.length());
                        }
                    }
                    FileDTO fileDTO =FileProcessor.saveFile(fileName);
                    MessageDTO messageDTO=new MessageDTO();
                    messageDTO.setConversationId(MessageDTO.conversationid);
                    messageDTO.setFileName(fileDTO.getFileName());
                    messageDTO.setFileUrl(fileDTO.getFileurl());
                    messageDTO.setSender("user");
                    messageDTO.setText(text);
                    messagesMapper.saveMessage(messageDTO);
                }
            }else{
                MessageDTO messageDTO=new MessageDTO();
                messageDTO.setConversationId(MessageDTO.conversationid);
                messageDTO.setSender("user");
                messageDTO.setText(text);
                messagesMapper.saveMessage(messageDTO);
            }
            // 3. 构建提示词
            StringBuilder promptBuilder = new StringBuilder();
            if (!userInput.isEmpty()) {
                promptBuilder.append("【用户问题】\n").append(userInput).append("\n");
            }
            if (!fileTextBuilder.isEmpty()) {
                promptBuilder.append("【参考文件】\n").append(fileTextBuilder);
            }
            promptBuilder.append("\n【回答要求】回答必须是纯自然语言，绝对不能包含'data:'、'{'、'}'等任何格式符号，直接输出内容，不要任何前缀。");
            promptBuilder.append("\n【任务要求】根据用户的提问以及上传的文件(如果有)做出回答，如果不是问题，请礼貌回答");
            String fullPrompt = FileProcessor.limitContentLength(promptBuilder.toString(), MAX_FULL_PROMPT_LENGTH);
            log.info("===== 构建的完整提示词 =====");
            log.info("提示词长度: {} 字符", fullPrompt.length());
            log.info("提示词内容: \n{}", fullPrompt);
            log.info("===========================");

            // 4. 添加用户消息到历史
            Map<String, Object> userMessage = new HashMap<>();
            userMessage.put("role", "user");
            userMessage.put("content", fullPrompt);
            if (!imageBase64List.isEmpty()) {
                userMessage.put("images", imageBase64List);
                log.debug("添加图片到用户消息，数量: {}", imageBase64List.size());
            }
            OllamaClient.chatHistory.add(userMessage);
            OllamaClient.trimHistory();
            log.info("用户消息已添加到历史，当前历史条数: {}", OllamaClient.chatHistory.size());

            // 5. 调用Ollama并处理响应
            final StringBuilder aiFullResponse = new StringBuilder();
            log.info("开始调用Ollama模型，等待流式响应...");

            return OllamaClient.callModelStream(OllamaClient.chatHistory)
                    // 包装为SSE格式
                    .map(cleanContent -> {
                        String sseChunk = "data: " + cleanContent + "\n\n";
                        log.debug("生成SSE分片: {}", sseChunk.length() > 50 ? sseChunk.substring(0, 50) + "..." : sseChunk);
                        return sseChunk;
                    })
                    // 记录每个分片
                    .doOnNext(sseChunk -> {
                        String content = sseChunk.substring(5, sseChunk.length() - 2).trim();
                        aiFullResponse.append(content);
                        log.debug("累计AI响应长度: {} 字符", aiFullResponse.length());
                    })
                    // 响应完成后处理
                    .doOnComplete(() -> {
                        Map<String, Object> assistantMessage = new HashMap<>();
                        assistantMessage.put("role", "assistant");
                        assistantMessage.put("content", aiFullResponse.toString());
                        OllamaClient.chatHistory.add(assistantMessage);
                        OllamaClient.trimHistory();
                        log.info("===== AI响应完成 =====");
                        log.info("完整响应长度: {} 字符", aiFullResponse.length());
                        log.info("完整响应内容: \n{}", aiFullResponse);
                        log.info("======================");
                        log.info("更新后历史条数: {}", OllamaClient.chatHistory.size());
                        MessageDTO messagedto=new MessageDTO();
                        messagedto.setConversationId(MessageDTO.conversationid);
                        messagedto.setSender("ai");
                        messagedto.setText(aiFullResponse.toString());
                        messagesMapper.saveMessage(messagedto);
                    });

        } catch (Exception e) {
            log.error("处理用户请求时发生异常", e);
            String errorMsg = "data: 服务异常：" + e.getMessage() + "\n\n";
            log.debug("返回错误SSE: {}", errorMsg);
            return Flux.just(errorMsg);
        }
    }

    public List<Messages> getHistory(Integer conversationId) {
        return messagesMapper.getHistory(conversationId);
    }
}